package com.xixing.weixin.web;

import com.xixing.weixin.cmd.CommandFactory;
import com.xixing.weixin.domain.School;
import com.xixing.weixin.domain.Weixin;
import com.xixing.weixin.response.Response;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.roo.addon.web.mvc.controller.scaffold.RooWebScaffold;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;

@RequestMapping("/weixins")
@Controller
@RooWebScaffold(path = "weixins", formBackingObject = Weixin.class, create = false, update = false, delete = false)
public class WeixinController {

    private static final Logger LOGGER = LoggerFactory.getLogger(WeixinController.class);

    @Autowired
    private CommandFactory commandFactory;

    /*
     * signature	 微信加密签名.
     * timestamp	 时间戳.
     * nonce	 随机数.
     * echostr	 随机字符串.
     *
     * */
    @RequestMapping(method = RequestMethod.GET, params = "signature")
    @ResponseBody
    public String siteAccess(@RequestParam(value = "signature") String signature, @RequestParam(value = "timestamp") String timestamp,
                             @RequestParam(value = "nonce") String nonce, @RequestParam(value = "echostr") String echostr) throws NoSuchAlgorithmException {
        LOGGER.info("signature={},timestamp={},nonce={},echostr={}", signature, timestamp, nonce, echostr);
        // 读取token.
        School school = findSchool(signature, timestamp, nonce);
        if (school != null) return echostr;

        LOGGER.warn("INVALID REQUEST");

        return "ERROR";
    }

    @RequestMapping(method = RequestMethod.POST, params = "signature")
    @ResponseBody
    public ResponseEntity<String> create(@RequestBody String xml, @RequestParam(value = "signature") String signature, @RequestParam(value = "timestamp") String timestamp,
                                         @RequestParam(value = "nonce") String nonce) throws IOException, NoSuchAlgorithmException {
        School school = findSchool(signature, timestamp, nonce);
        if (school != null) {
            LOGGER.info("XML:{}", xml);

            Weixin weixin = Weixin.fromXml(xml);
            weixin.persist();

            if(StringUtils.isBlank(school.getWeixinCode())) {
                school.setWeixinCode(weixin.getToUserName());
                school.merge();
            }


            Response response =  commandFactory.execute(weixin);

            String res = response.toXml();
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", " text/xml;charset=UTF-8");
            return new ResponseEntity<String>(res, headers, HttpStatus.OK);
        }
        return new ResponseEntity<String>("", HttpStatus.BAD_REQUEST);
    }

    private School findSchool(String signature, String timestamp, String nonce) throws NoSuchAlgorithmException {
        List<School> allSchools = School.findAllSchools();
        for (School school : allSchools) {
            // 加密/校验流程.

            // 1. 将token、timestamp、nonce三个参数进行字典序排序.
            String[] params = {school.getWeixinToken(), timestamp, nonce};
            Arrays.sort(params);


            // 2. 将三个参数字符串拼接成一个字符串进行sha1加密 .
            String joined = StringUtils.join(params);
            MessageDigest digest = MessageDigest.getInstance("SHA1");
            byte[] sha1 = digest.digest(joined.getBytes());
            String sha1Hex = Hex.encodeHexString(sha1);
            LOGGER.debug("SITE ACCESS SIGNATURE:" + sha1Hex);


            // 3. 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信 .
            if (signature.equalsIgnoreCase(sha1Hex)) {
                return school;
            }
        }
        return null;
    }
}
